const util = require("./util");

/**
 * 枚举类
 * @param {Object} enumMap 枚举对象
 * 枚举格式：
 * {
 *    枚举key1: [枚举值2，枚举描述2],
 *    枚举key2: [枚举值2，枚举描述2]
 * }
 */
class EnumBase {
	/**
	 * @param {Object} enumMap 枚举map
	 * @param {String} description 枚举描述
	 */
	constructor(enumMap = {}, description) {
		if (!util.isType(enumMap, "object")) {
			throw new TypeError("The argument should be an object！");
		}
		this._init(util.deepClone(enumMap), description);
	}

	/**
	 * 初始化
	 * @param {Object} enumMap 枚举对象
	 * @param {String} description 描述
	 * @private
	 */
	_init(enumMap, description) {
		this.__enumMap__ = enumMap;
		this.description = description;
		this._setProxy(enumMap); //设置代理
	}

	/**
	 * 设置代理
	 * @param {Object} enumMap
	 * @private
	 */
	_setProxy(enumMap) {
		const keys = Object.keys(enumMap);
		keys.forEach(key => {
			Object.defineProperty(this, key, {
				get: () => {
					return this.getVal(key);
				}
			});
		});
	}

	/**
	 * 获取枚举值
	 * @param {String} key 枚举KEY
	 * @return {Number} 枚举值
	 */
	getVal(key) {
		return util.dGet(this.__enumMap__, [key, 0], null);
	}

	/**
	 * 获取多个枚举值
	 * @param {Array} paramN 多个枚举KEY
	 * @return {Array} {[枚举key], 枚举值}
	 */
	getValList(...args) {
		if (!Array.isArray(args) || !args.every(type => typeof type === "string")) {
			return {};
		}
		return args.map(type => this.getVal(type));
	}

	/**
	 * 获取多个枚举值Map
	 * @param {Array} param 多个枚举KEY，如果不传递则返回所有
	 * @return {Object} {[枚举key], 枚举值}
	 */
	getValMap(...args) {
		if (Array.isArray(args) && !args.every(type => typeof type === "string")) {
			return {};
		}
		const keys = Object.keys(this.__enumMap__); // 不传递返回
		return keys.reduce((wrap, key) => {
			wrap[key] = this.getVal(key);
			return wrap;
		}, {});
	}

	/**
	 * 获取枚举名称
	 * @param {String} key 枚举KEY
	 * @return {String} 枚举名称
	 */
	getName(key) {
		return util.dGet(this.__enumMap__, [key, 1], null);
	}

	/**
	 * 通过枚举值获取枚举名称
	 * @param {String|Nunber} val
	 * @return {String|Null}
	 */
	getNameByValue(val) {
		if (!val) return null;
		// 获取对象key
		return util.findObjectKey(this.__enumMap__, valItm => valItm[0] === val, null);
	}

	/**
	 * 获取枚举值名称
	 * @param {String|Nunber} val
	 * @return {String} name
	 */
	getValName(val) {
		const enumItem = Object.values(this.__enumMap__).find(v => v[0] === val);
		return enumItem ? enumItem[1] : "";
	}

	/**
	 * 检测字段类型
	 * @param {Number} typeVal 类型
	 * @param {String} typeKey 类型key
	 * @return {Boolean}
	 */
	check(typeVal, typeKey) {
		return this.getVal(typeKey) === typeVal;
	}
}

// export
module.exports = EnumBase;
